package com.swak.config.setting;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;

import org.springframework.core.io.FileSystemResource;

import com.google.common.io.Files;
import com.swak.fx.support.ui.UI.Conts;
import com.swak.utils.Maps;
import com.swak.utils.StringUtils;

/**
 * 优化系统配置
 * 
 * @author lifeng
 */
public class Settings {

	private static final String Config_Name = "config";
	private static final String Settings_Name = "settings.properties";
	private static final String Resources_Name = "/src/main/resources/";
	private static volatile Settings CONTEXT;

	public static Settings me() {
		return CONTEXT;
	}

	/**
	 * 默认取这个文件的路径
	 * 
	 * @param args
	 * @return
	 */
	public static Settings intSettings() {
		if (CONTEXT == null) {
			synchronized (Settings.class) {
				if (CONTEXT == null) {
					CONTEXT = Settings.init();
				}
			}
		}
		return CONTEXT;
	}

	/**
	 * 初始化
	 * 
	 * @return
	 */
	private synchronized static Settings init() {
		try {
			FileSystemResource resource = new FileSystemResource(StringUtils.EMPTY);
			File baseFile = resource.getFile().getAbsoluteFile();
			File basePath = baseFile, configPath = new File(baseFile, Resources_Name);
			if (new File(baseFile, Config_Name).exists()) {
				configPath = new File(baseFile, Config_Name);
			}
			Settings settings = new Settings();
			settings.basePath = basePath;
			settings.configPath = configPath;
			settings.handleConfig();
			return settings;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private File basePath;
	private File configPath;
	private Properties $config = new Properties();
	private Map<String, String> config = Maps.newHashMap();
	private AtomicBoolean md = new AtomicBoolean(false);

	/**
	 * 个性化配置
	 */
	private Runtime runtime;

	public File getBasePath() {
		return basePath;
	}

	protected void handleConfig() {
		try {
			File version = new File(configPath, Settings_Name);
			$config.load(Files.asCharSource(version, StandardCharsets.UTF_8).openStream());
			$config.keySet().forEach(key -> {
				config.put(String.valueOf(key), String.valueOf($config.get(key)));
			});
		} catch (Exception e) {
			$config = new Properties();
		}
	}

	public Map<String, String> getConfig() {
		return config;
	}

	public void storeConfig() {

		// 保存私域配置
		if (this.runtime != null) {
			this.runtime.storeConfig();
		}

		// 保存全局配置
		this.storeGlobalConfig();
	}

	public void storeGlobalConfig() {
		if (!md.get()) {
			return;
		}
		try {
			File version = new File(configPath, Settings_Name);
			config.keySet().forEach(key -> {
				$config.put(key, config.get(key));
			});
			$config.store(Files.newWriter(version, StandardCharsets.UTF_8), Settings_Name);
		} catch (Exception e) {
		}
	}

	public void putConfig(String key, String value) {
		if (this.runtime != null) {
			this.runtime.putConfig(key, value);
			return;
		}
		this.md.compareAndExchange(false, true);
		this.config.put(key, value);
	}

	public String getConfig(String key) {
		String value = this.runtime != null ? this.runtime.getConfig(key) : null;
		value = value != null ? value : config.get(key);
		return value == null ? StringUtils.EMPTY : value;
	}

	public String getConfig(String key, String def) {
		String value = this.runtime != null ? this.runtime.getConfig(key) : null;
		value = value != null ? value : config.get(key);
		return value == null ? def : value;
	}

	public File getTempFile() {
		return new File(this.getBasePath(), Conts.TempPath);
	}

	public File getRuntimeFile() {
		return new File(this.getBasePath(), Conts.RuntimePath);
	}

	/**
	 * 在 RuntimeFile 目录下开启私域化配置
	 * 
	 * @param name
	 */
	public void enableRuntime(String name) {
		this.runtime = new Runtime(name);
	}
}